package org.eclipse.iee.pad.graph.ui;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import java.util.ResourceBundle;
import javax.swing.event.EventListenerList;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.FileDialog;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.entity.ChartEntity;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.event.ChartChangeEvent;
import org.jfree.chart.event.ChartChangeListener;
import org.jfree.chart.event.ChartProgressEvent;
import org.jfree.chart.event.ChartProgressListener;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.ValueAxisPlot;
import org.jfree.chart.plot.Zoomable;
import org.jfree.chart.util.ResourceBundleWrapper;
import org.jfree.experimental.swt.SWTUtils;
public class ChartFigure extends Figure implements ChartChangeListener,
ChartProgressListener {
/** Default setting for buffer usage. */
public static final boolean DEFAULT_BUFFER_USED = false;
/** The default panel width. */
public static final int DEFAULT_WIDTH = 680;
/** The default panel height. */
public static final int DEFAULT_HEIGHT = 420;
/** The default limit below which chart scaling kicks in. */
public static final int DEFAULT_MINIMUM_DRAW_WIDTH = 300;
/** The default limit below which chart scaling kicks in. */
public static final int DEFAULT_MINIMUM_DRAW_HEIGHT = 200;
/** The default limit below which chart scaling kicks in. */
public static final int DEFAULT_MAXIMUM_DRAW_WIDTH = 800;
/** The default limit below which chart scaling kicks in. */
public static final int DEFAULT_MAXIMUM_DRAW_HEIGHT = 600;
/** The minimum size required to perform a zoom on a rectangle */
public static final int DEFAULT_ZOOM_TRIGGER_DISTANCE = 10;
/** The chart that is displayed in the panel. */
private JFreeChart chart;
private final Graphics2DRenderer renderer = new Graphics2DRenderer();
private IShellProvider shellProvider;
/** Storage for registered (chart) mouse listeners. */
private EventListenerList chartMouseListeners;
/** A buffer for the rendered chart. */
private org.eclipse.swt.graphics.Image chartBuffer;
/**
* The minimum width for drawing a chart (uses scaling for smaller widths).
*/
private int minimumDrawWidth;
/**
* The minimum height for drawing a chart (uses scaling for smaller
* heights).
*/
private int minimumDrawHeight;
/**
* The maximum width for drawing a chart (uses scaling for bigger
* widths).
*/
private int maximumDrawWidth;
/**
* The maximum height for drawing a chart (uses scaling for bigger
* heights).
*/
private int maximumDrawHeight;
/** The drawing info collected the last time the chart was drawn. */
private ChartRenderingInfo info;
/** The chart anchor point. */
private Point2D anchor;
/** The scale factor used to draw the chart. */
private double scaleX;
/** The scale factor used to draw the chart. */
private double scaleY;
/** A flag that controls whether or not domain zooming is enabled. */
private boolean domainZoomable = false;
/** A flag that controls whether or not range zooming is enabled. */
private boolean rangeZoomable = false;
/**
* The zoom rectangle starting point (selected by the user with a mouse
* click). This is a point on the screen, not the chart (which may have
* been scaled up or down to fit the panel).
*/
private org.eclipse.swt.graphics.Point zoomPoint = null;
/** The zoom rectangle (selected by the user with the mouse). */
private transient org.eclipse.draw2d.geometry.Rectangle zoomRectangle = null;
/** Controls if the zoom rectangle is drawn as an outline or filled. */
//TODO private boolean fillZoomRectangle = true;
/** A flag that controls whether or not horizontal tracing is enabled. */
private boolean horizontalAxisTrace = false;
/** A flag that controls whether or not vertical tracing is enabled. */
private boolean verticalAxisTrace = false;
/** A vertical trace line. */
private transient int verticalTraceLineX;
/** A horizontal trace line. */
private transient int horizontalTraceLineY;
/** A flag that controls whether or not file extensions are enforced. */
private boolean enforceFileExtensions;
/** The factor used to zoom in on an axis range. */
private double zoomInFactor = 0.5;
/** The factor used to zoom out on an axis range. */
private double zoomOutFactor = 2.0;
/** The resourceBundle for the localization. */
protected static ResourceBundle localizationResources
= ResourceBundleWrapper.getBundle(
"org.jfree.chart.LocalizationBundle");
private Label fTooltip;
/**
* Constructs a panel that displays the specified chart.
*
* @param comp The parent.
* @param style The style of the composite.
* @param chart the chart.
*/
public ChartFigure(JFreeChart chart,
IShellProvider shellProvider) {
this(chart,
DEFAULT_WIDTH,
DEFAULT_HEIGHT,
DEFAULT_MINIMUM_DRAW_WIDTH,
DEFAULT_MINIMUM_DRAW_HEIGHT,
DEFAULT_MAXIMUM_DRAW_WIDTH,
DEFAULT_MAXIMUM_DRAW_HEIGHT,
DEFAULT_BUFFER_USED,
true, // properties
shellProvider
);
}
/**
* Constructs a panel containing a chart.
*
* @param comp The parent.
* @param style The style of the composite.
* @param chart the chart.
* @param useBuffer a flag controlling whether or not an off-screen buffer
* is used.
*/
public ChartFigure(JFreeChart chart,
boolean useBuffer,
IShellProvider shellProvider) {
this(chart,
DEFAULT_WIDTH,
DEFAULT_HEIGHT,
DEFAULT_MINIMUM_DRAW_WIDTH,
DEFAULT_MINIMUM_DRAW_HEIGHT,
DEFAULT_MAXIMUM_DRAW_WIDTH,
DEFAULT_MAXIMUM_DRAW_HEIGHT,
useBuffer,
true, // properties
shellProvider);
}
/**
* Constructs a JFreeChart panel.
* @param jfreechart the chart.
* @param width the preferred width of the panel.
* @param height the preferred height of the panel.
* @param minimumDrawW the minimum drawing width.
* @param minimumDrawH the minimum drawing height.
* @param maximumDrawW the maximum drawing width.
* @param maximumDrawH the maximum drawing height.
* @param usingBuffer a flag that indicates whether to use the off-screen
* buffer to improve performance (at the expense of
* memory).
* @param tooltips a flag indicating whether or not tooltips should be
* enabled for the chart.
* @param comp The parent.
* @param style The style of the composite.
*/
public ChartFigure(JFreeChart jfreechart,
int width,
int height,
int minimumDrawW,
int minimumDrawH,
int maximumDrawW,
int maximumDrawH,
boolean usingBuffer,
boolean tooltips,
IShellProvider shellProvider) {
setChart(jfreechart);
this.shellProvider = shellProvider;
this.chartMouseListeners = new EventListenerList();
this.info = new ChartRenderingInfo();
this.minimumDrawWidth = minimumDrawW;
this.minimumDrawHeight = minimumDrawH;
this.maximumDrawWidth = maximumDrawW;
this.maximumDrawHeight = maximumDrawH;
this.enforceFileExtensions = true;
fTooltip = new Label();
setToolTip(fTooltip);
}
/**
* Returns the X scale factor for the chart. This will be 1.0 if no
* scaling has been used.
*
* @return The scale factor.
*/
public double getScaleX() {
return this.scaleX;
}
/**
* Returns the Y scale factory for the chart. This will be 1.0 if no
* scaling has been used.
*
* @return The scale factor.
*/
public double getScaleY() {
return this.scaleY;
}
/**
* Returns the anchor point.
*
* @return The anchor point (possibly <code>null</code>).
*/
public Point2D getAnchor() {
return this.anchor;
}
/**
* Sets the anchor point. This method is provided for the use of
* subclasses, not end users.
*
* @param anchor the anchor point (<code>null</code> permitted).
*/
protected void setAnchor(Point2D anchor) {
this.anchor = anchor;
}
/**
* Returns the chart contained in the panel.
*
* @return The chart (possibly <code>null</code>).
*/
public JFreeChart getChart() {
return this.chart;
}
/**
* Sets the chart that is displayed in the panel.
*
* @param chart the chart (<code>null</code> permitted).
*/
public void setChart(JFreeChart chart) {
// stop listening for changes to the existing chart
if (this.chart != null) {
this.chart.removeChangeListener(this);
this.chart.removeProgressListener(this);
}
// add the new chart
this.chart = chart;
if (chart != null) {
this.chart.addChangeListener(this);
this.chart.addProgressListener(this);
Plot plot = chart.getPlot();
this.domainZoomable = false;
this.rangeZoomable = false;
if (plot instanceof Zoomable) {
Zoomable z = (Zoomable) plot;
this.domainZoomable = z.isDomainZoomable();
this.rangeZoomable = z.isRangeZoomable();
}
}
else {
this.domainZoomable = false;
this.rangeZoomable = false;
}
}
/**
* Returns the chart rendering info from the most recent chart redraw.
*
* @return The chart rendering info (possibly <code>null</code>).
*/
public ChartRenderingInfo getChartRenderingInfo() {
return this.info;
}
/**
* Returns the flag that determines whether or not zooming is enabled for
* the domain axis.
*
* @return A boolean.
*/
public boolean isDomainZoomable() {
return this.domainZoomable;
}
/**
* Sets the flag that controls whether or not zooming is enable for the
* domain axis. A check is made to ensure that the current plot supports
* zooming for the domain values.
*
* @param flag <code>true</code> enables zooming if possible.
*/
public void setDomainZoomable(boolean flag) {
if (flag) {
Plot plot = this.chart.getPlot();
if (plot instanceof Zoomable) {
Zoomable z = (Zoomable) plot;
this.domainZoomable = flag && (z.isDomainZoomable());
}
}
else {
this.domainZoomable = false;
}
}
/**
* Returns the flag that determines whether or not zooming is enabled for
* the range axis.
*
* @return A boolean.
*/
public boolean isRangeZoomable() {
return this.rangeZoomable;
}
/**
* A flag that controls mouse-based zooming on the vertical axis.
*
* @param flag <code>true</code> enables zooming.
*/
public void setRangeZoomable(boolean flag) {
if (flag) {
Plot plot = this.chart.getPlot();
if (plot instanceof Zoomable) {
Zoomable z = (Zoomable) plot;
this.rangeZoomable = flag && (z.isRangeZoomable());
}
}
else {
this.rangeZoomable = false;
}
}
/**
* Returns the zoom in factor.
*
* @return The zoom in factor.
*
* @see #setZoomInFactor(double)
*/
public double getZoomInFactor() {
return this.zoomInFactor;
}
/**
* Sets the zoom in factor.
*
* @param factor the factor.
*
* @see #getZoomInFactor()
*/
public void setZoomInFactor(double factor) {
this.zoomInFactor = factor;
}
/**
* Returns the zoom out factor.
*
* @return The zoom out factor.
*
* @see #setZoomOutFactor(double)
*/
public double getZoomOutFactor() {
return this.zoomOutFactor;
}
/**
* Sets the zoom out factor.
*
* @param factor the factor.
*
* @see #getZoomOutFactor()
*/
public void setZoomOutFactor(double factor) {
this.zoomOutFactor = factor;
}
/**
* Returns <code>true</code> if file extensions should be enforced, and
* <code>false</code> otherwise.
*
* @return The flag.
*/
public boolean isEnforceFileExtensions() {
return this.enforceFileExtensions;
}
/**
* Sets a flag that controls whether or not file extensions are enforced.
*
* @param enforce the new flag value.
*/
public void setEnforceFileExtensions(boolean enforce) {
this.enforceFileExtensions = enforce;
}
/**
* Opens a file chooser and gives the user an opportunity to save the chart
* in PNG format.
*
* @throws IOException if there is an I/O error.
*/
public void doSaveAs() throws IOException {
FileDialog fileDialog = new FileDialog(shellProvider.getShell(),
SWT.SAVE);
String[] extensions = {"*.png"};
fileDialog.setFilterExtensions(extensions);
String filename = fileDialog.open();
if (filename != null) {
if (isEnforceFileExtensions()) {
if (!filename.endsWith(".png")) {
filename = filename + ".png";
}
}
//TODO replace getSize by getBounds ?
org.eclipse.draw2d.geometry.Rectangle bounds = getBounds();
ChartUtilities.saveChartAsPNG(new File(filename), this.chart,
bounds.getSize().width, bounds.getSize().height);
}
}
/**
* Zooms in on an anchor point (specified in screen coordinate space).
*
* @param x the x value (in screen coordinates).
* @param y the y value (in screen coordinates).
*/
public void zoomInBoth(double x, double y) {
zoomInDomain(x, y);
zoomInRange(x, y);
}
/**
* Decreases the length of the domain axis, centered about the given
* coordinate on the screen. The length of the domain axis is reduced
* by the value of {@link #getZoomInFactor()}.
*
* @param x the x coordinate (in screen coordinates).
* @param y the y-coordinate (in screen coordinates).
*/
public void zoomInDomain(double x, double y) {
Plot p = this.chart.getPlot();
if (p instanceof Zoomable)
{
Zoomable plot = (Zoomable) p;
plot.zoomDomainAxes(this.zoomInFactor, this.info.getPlotInfo(),
translateScreenToJava2D(new Point((int) x, (int) y)));
}
}
/**
* Decreases the length of the range axis, centered about the given
* coordinate on the screen. The length of the range axis is reduced by
* the value of {@link #getZoomInFactor()}.
*
* @param x the x-coordinate (in screen coordinates).
* @param y the y coordinate (in screen coordinates).
*/
public void zoomInRange(double x, double y) {
Plot p = this.chart.getPlot();
if (p instanceof Zoomable) {
Zoomable z = (Zoomable) p;
z.zoomRangeAxes(this.zoomInFactor, this.info.getPlotInfo(),
translateScreenToJava2D(new Point((int) x, (int) y)));
}
}
/**
* Zooms out on an anchor point (specified in screen coordinate space).
*
* @param x the x value (in screen coordinates).
* @param y the y value (in screen coordinates).
*/
public void zoomOutBoth(double x, double y) {
zoomOutDomain(x, y);
zoomOutRange(x, y);
}
/**
* Increases the length of the domain axis, centered about the given
* coordinate on the screen. The length of the domain axis is increased
* by the value of {@link #getZoomOutFactor()}.
*
* @param x the x coordinate (in screen coordinates).
* @param y the y-coordinate (in screen coordinates).
*/
public void zoomOutDomain(double x, double y) {
Plot p = this.chart.getPlot();
if (p instanceof Zoomable) {
Zoomable z = (Zoomable) p;
z.zoomDomainAxes(this.zoomOutFactor, this.info.getPlotInfo(),
translateScreenToJava2D(new Point((int) x, (int) y)));
}
}
/**
* Increases the length the range axis, centered about the given
* coordinate on the screen. The length of the range axis is increased
* by the value of {@link #getZoomOutFactor()}.
*
* @param x the x coordinate (in screen coordinates).
* @param y the y-coordinate (in screen coordinates).
*/
public void zoomOutRange(double x, double y) {
Plot p = this.chart.getPlot();
if (p instanceof Zoomable) {
Zoomable z = (Zoomable) p;
z.zoomRangeAxes(this.zoomOutFactor, this.info.getPlotInfo(),
translateScreenToJava2D(new Point((int) x, (int) y)));
}
}
/**
* Zooms in on a selected region.
*
* @param zoomRectangle2 the selected region.
*/
public void zoom(org.eclipse.draw2d.geometry.Rectangle zoomRectangle2) {
// get the origin of the zoom selection in the Java2D space used for
// drawing the chart (that is, before any scaling to fit the panel)
Point2D selectOrigin = translateScreenToJava2D(
new Point(zoomRectangle2.x, zoomRectangle2.y));
PlotRenderingInfo plotInfo = this.info.getPlotInfo();
Rectangle scaledDataArea = getScreenDataArea(
(zoomRectangle2.x + zoomRectangle2.width / 2),
(zoomRectangle2.y + zoomRectangle2.height / 2));
if ((zoomRectangle2.height > 0) && (zoomRectangle2.width > 0)) {
double hLower = (zoomRectangle2.x - scaledDataArea.x)
/ (double) scaledDataArea.width;
double hUpper = (zoomRectangle2.x + zoomRectangle2.width - scaledDataArea.x)
/ (double) scaledDataArea.width;
double vLower = (scaledDataArea.y + scaledDataArea.height
- zoomRectangle2.y - zoomRectangle2.height)
/ (double) scaledDataArea.height;
double vUpper = (scaledDataArea.y + scaledDataArea.height
- zoomRectangle2.y) / (double) scaledDataArea.height;
Plot p = this.chart.getPlot();
if (p instanceof Zoomable) {
Zoomable z = (Zoomable) p;
if (z.getOrientation() == PlotOrientation.HORIZONTAL) {
z.zoomDomainAxes(vLower, vUpper, plotInfo, selectOrigin);
z.zoomRangeAxes(hLower, hUpper, plotInfo, selectOrigin);
}
else {
z.zoomDomainAxes(hLower, hUpper, plotInfo, selectOrigin);
z.zoomRangeAxes(vLower, vUpper, plotInfo, selectOrigin);
}
}
}
}
/**
* Receives notification of changes to the chart, and redraws the chart.
*
* @param event details of the chart change event.
*/
public void chartChanged(ChartChangeEvent event) {
repaint();
}
/**
* Forces a redraw of the canvas by invoking a new PaintEvent.
*/
public void forceRedraw() {
repaint();
}
/**
* Adds a listener to the list of objects listening for chart mouse events.
*
* @param listener the listener (<code>null</code> not permitted).
*/
public void addChartMouseListener(ChartMouseListener listener) {
this.chartMouseListeners.add(ChartMouseListener.class, listener);
}
/**
* Removes a listener from the list of objects listening for chart mouse
* events.
*
* @param listener the listener.
*/
public void removeChartMouseListener(ChartMouseListener listener) {
this.chartMouseListeners.remove(ChartMouseListener.class, listener);
}
/**
* Receives notification of a chart progress event.
*
* @param event the event.
*/
public void chartProgress(ChartProgressEvent event) {
// does nothing - override if necessary
}
/**
* Restores the auto-range calculation on both axes.
*/
public void restoreAutoBounds() {
restoreAutoDomainBounds();
restoreAutoRangeBounds();
}
/**
* Restores the auto-range calculation on the domain axis.
*/
public void restoreAutoDomainBounds() {
Plot p = this.chart.getPlot();
if (p instanceof Zoomable) {
Zoomable z = (Zoomable) p;
// we need to guard against this.zoomPoint being null
org.eclipse.swt.graphics.Point zp =
(this.zoomPoint != null ? this.zoomPoint
: new org.eclipse.swt.graphics.Point(0, 0));
z.zoomDomainAxes(0.0, this.info.getPlotInfo(),
SWTUtils.toAwtPoint(zp));
}
}
/**
* Restores the auto-range calculation on the range axis.
*/
public void restoreAutoRangeBounds() {
Plot p = this.chart.getPlot();
if (p instanceof ValueAxisPlot) {
Zoomable z = (Zoomable) p;
// we need to guard against this.zoomPoint being null
org.eclipse.swt.graphics.Point zp =
(this.zoomPoint != null ? this.zoomPoint
: new org.eclipse.swt.graphics.Point(0, 0));
z.zoomRangeAxes(0.0, this.info.getPlotInfo(),
SWTUtils.toAwtPoint(zp));
}
}
/**
* Applies any scaling that is in effect for the chart drawing to the
* given rectangle.
*
* @param rect the rectangle.
*
* @return A new scaled rectangle.
*/
public Rectangle scale(Rectangle2D rect) {
org.eclipse.draw2d.geometry.Rectangle insets = this.getClientArea();
int x = (int) Math.round(rect.getX() * getScaleX()) + insets.x;
int y = (int) Math.round(rect.getY() * this.getScaleY()) + insets.y;
int w = (int) Math.round(rect.getWidth() * this.getScaleX());
int h = (int) Math.round(rect.getHeight() * this.getScaleY());
return new Rectangle(x, y, w, h);
}
/**
* Returns the data area for the chart (the area inside the axes) with the
* current scaling applied (that is, the area as it appears on screen).
*
* @return The scaled data area.
*/
public Rectangle getScreenDataArea() {
Rectangle2D dataArea = this.info.getPlotInfo().getDataArea();
org.eclipse.draw2d.geometry.Rectangle clientArea = this.getClientArea();
int x = (int) (dataArea.getX() * this.scaleX + clientArea.x);
int y = (int) (dataArea.getY() * this.scaleY + clientArea.y);
int w = (int) (dataArea.getWidth() * this.scaleX);
int h = (int) (dataArea.getHeight() * this.scaleY);
return new Rectangle(x, y, w, h);
}
/**
* Returns the data area (the area inside the axes) for the plot or subplot,
* with the current scaling applied.
*
* @param x the x-coordinate (for subplot selection).
* @param y the y-coordinate (for subplot selection).
*
* @return The scaled data area.
*/
public Rectangle getScreenDataArea(int x, int y) {
PlotRenderingInfo plotInfo = this.info.getPlotInfo();
Rectangle result;
if (plotInfo.getSubplotCount() == 0)
result = getScreenDataArea();
else {
// get the origin of the zoom selection in the Java2D space used for
// drawing the chart (that is, before any scaling to fit the panel)
Point2D selectOrigin = translateScreenToJava2D(new Point(x, y));
int subplotIndex = plotInfo.getSubplotIndex(selectOrigin);
if (subplotIndex == -1) {
return null;
}
result = scale(plotInfo.getSubplotInfo(subplotIndex).getDataArea());
}
return result;
}
/**
* Translates a Java2D point on the chart to a screen location.
*
* @param java2DPoint the Java2D point.
*
* @return The screen location.
*/
public Point translateJava2DToScreen(Point2D java2DPoint) {
org.eclipse.draw2d.geometry.Rectangle insets = this.getClientArea();
int x = (int) (java2DPoint.getX() * this.scaleX + insets.x);
int y = (int) (java2DPoint.getY() * this.scaleY + insets.y);
return new Point(x, y);
}
/**
* Translates a screen location to a Java SWT point.
*
* @param screenPoint the screen location.
*
* @return The Java2D coordinates.
*/
public Point translateScreenToJavaSWT(Point screenPoint) {
org.eclipse.draw2d.geometry.Rectangle insets = this.getClientArea();
int x = (int) ((screenPoint.x - insets.x) / this.scaleX);
int y = (int) ((screenPoint.y - insets.y) / this.scaleY);
return new Point(x, y);
}
/**
* Translates a screen location to a Java2D point.
*
* @param screenPoint the screen location.
*
* @return The Java2D coordinates.
*/
public Point2D translateScreenToJava2D(Point screenPoint) {
org.eclipse.draw2d.geometry.Rectangle insets = this.getClientArea();
int x = (int) ((screenPoint.x - insets.x) / this.scaleX);
int y = (int) ((screenPoint.y - insets.y) / this.scaleY);
return new Point2D.Double(x, y);
}
/**
* Returns the flag that controls whether or not a horizontal axis trace
* line is drawn over the plot area at the current mouse location.
*
* @return A boolean.
*/
public boolean getHorizontalAxisTrace() {
return this.horizontalAxisTrace;
}
/**
* A flag that controls trace lines on the horizontal axis.
*
* @param flag <code>true</code> enables trace lines for the mouse
* pointer on the horizontal axis.
*/
public void setHorizontalAxisTrace(boolean flag) {
this.horizontalAxisTrace = flag;
}
/**
* Returns the flag that controls whether or not a vertical axis trace
* line is drawn over the plot area at the current mouse location.
*
* @return A boolean.
*/
public boolean getVerticalAxisTrace() {
return this.verticalAxisTrace;
}
/**
* A flag that controls trace lines on the vertical axis.
*
* @param flag <code>true</code> enables trace lines for the mouse
* pointer on the vertical axis.
*/
public void setVerticalAxisTrace(boolean flag) {
this.verticalAxisTrace = flag;
}
/**
* Returns a string for the tooltip.
*
* @param e the mouse event.
*
* @return A tool tip or <code>null</code> if no tooltip is available.
*/
public String getToolTipText(MouseEvent e) {
String result = null;
if (this.info != null) {
EntityCollection entities = this.info.getEntityCollection();
if (entities != null) {
org.eclipse.draw2d.geometry.Rectangle insets = getClientArea();
ChartEntity entity = entities.getEntity(
(int) ((e.x - insets.x) / this.scaleX),
(int) ((e.y - insets.y) / this.scaleY));
if (entity != null) {
result = entity.getToolTipText();
}
}
}
return result;
}
@Override
protected void paintClientArea(Graphics graphics) {
// first determine the size of the chart rendering area...
// TODO workout insets for SWT
org.eclipse.draw2d.geometry.Rectangle available = getBounds();
// skip if chart is null
if (this.chart == null) {
graphics.drawRectangle(available.x, available.y,
available.width, available.height);
return;
}
// work out if scaling is required...
int drawWidth = available.width;
int drawHeight = available.height;
if (drawWidth == 0.0 || drawHeight == 0.0) return;
this.scaleX = 1.0;
this.scaleY = 1.0;
if (drawWidth < this.minimumDrawWidth) {
this.scaleX = (double) drawWidth / this.minimumDrawWidth;
drawWidth = this.minimumDrawWidth;
}
else if (drawWidth > this.maximumDrawWidth) {
this.scaleX = (double) drawWidth / this.maximumDrawWidth;
drawWidth = this.maximumDrawWidth;
}
if (drawHeight < this.minimumDrawHeight) {
this.scaleY = (double) drawHeight / this.minimumDrawHeight;
drawHeight = this.minimumDrawHeight;
}
else if (drawHeight > this.maximumDrawHeight) {
this.scaleY = (double) drawHeight / this.maximumDrawHeight;
drawHeight = this.maximumDrawHeight;
}
org.eclipse.draw2d.geometry.Rectangle bounds = getBounds();
graphics.translate(bounds.x, bounds.y);
renderer.prepareRendering(graphics);
Graphics2D graphics2d = renderer.getGraphics2D();
this.chart.draw(graphics2d, new Rectangle2D.Double(0, 0,
bounds.width, bounds.height), getAnchor(),
this.info);
renderer.render(graphics);
graphics.translate(-bounds.x, -bounds.y);
Rectangle area = getScreenDataArea();
if (this.horizontalAxisTrace && area.x < this.verticalTraceLineX
&& area.x + area.width > this.verticalTraceLineX) {
graphics.drawLine(this.verticalTraceLineX, area.y,
this.verticalTraceLineX, area.y + area.height);
}
if (this.verticalAxisTrace && area.y < this.horizontalTraceLineY
&& area.y + area.height > this.horizontalTraceLineY) {
graphics.drawLine(area.x, this.horizontalTraceLineY,
area.x + area.width, this.horizontalTraceLineY);
}
this.verticalTraceLineX = 0;
this.horizontalTraceLineY = 0;
if (this.zoomRectangle != null) {
graphics.drawRectangle(this.zoomRectangle);
}
}
/**
* Disposes the control.
*/
public void dispose() {
if (this.chartBuffer != null) this.chartBuffer.dispose();
// de-register the composite as a listener for the chart.
if (this.chart != null) {
this.chart.removeChangeListener(this);
this.chart.removeProgressListener(this);
}
renderer.dispose();
}
}